package ua.kpi_java_training5.kereia.module1;
import java.util.Scanner;
/**
 * Program for division in column
 * @author Alex Kereia
 * @since 2013-05-18
 */
public class Division {
    Integer [] dividend;
    int divisor;
    String result = "";
    static int gapsBefore = 0;
    
    public Division(Integer [] dividend, int divisor) {
        this.divisor = divisor;
        this.dividend = dividend;
    }
    
    public Division() {
        dividend = saveDividendFromConsole();
        divisor = Integer.valueOf(getFromConsole("Enter the divisor: "));
    }
    
    public static void main(String[] args) {
        Division div = new Division();
        div.makeColumn(div.dividend[1]);
        System.out.println("Result = "+div.result);
    }
    
    /**
     * Increase value gaps before numbers
     * @param i 
     */
    public void increaseGapsBefore(int i) {
        gapsBefore = gapsBefore + i;
    }
    /**
     * Setter for result with integer parameter in constructor
     * @param intermediateResult 
     */
    public void setResult(int intermediateResult) {
        result = result + intermediateResult;
    }
    
    /**
     * Setter for result with String parameter in constructor
     * @param intermediateResult 
     */
    public void setResult(String intermediateResult) {
        result = result + intermediateResult;
    }
    /**
     * Method which get data from comand line and return that
     * @return int
     */
    public static String getFromConsole(String text) {
            Scanner scan = new Scanner(System.in);
            System.out.print(text);
            String a = scan.nextLine();
            return a;
    }
    /**
     * Metod which save dividend as Integer array, and return that
     * @return 
     */
    public static Integer [] saveDividendFromConsole() {
        String divid = getFromConsole("Enter the dividend: ");
        String [] line = divid.split("");
        Integer [] dividendIntermediate = new Integer[line.length];
        for(int i = 1;i <= divid.length();i++) {
            dividendIntermediate[i] = Integer.valueOf(line[i]);
        }
        return dividendIntermediate;
    }
    /**
     * Compose two digits in one
     * @param firstNumber
     * @param secondNumber
     * @return int value that number
     * 
     */
    public static int generateNumberFromTwo(int firstNumber, int secondNumber) {
        int result = 0;
        int counter = 10;
            while(counter < 1000000) {
                if(firstNumber < counter) {
                    result = firstNumber * 10 + secondNumber;
                    break;
                }
                counter = counter * 10;
            }
        return result;
    }
    
    boolean markerPrintHead = true;
    int valueUndescoreLine = 0;
    /**
     * Metod which generate and print column
     */
    public void makeColumn(int dividend) {
        int firstPart = dividend;
        for(int i = 0;i < 20;i++) {
        int remainderAndAddition = generateSuitablePartOfDividend(firstPart);
        if(firstPart == 0 && valueUndescoreLine != 0) {
            increaseGapsBefore(returnCategoryOfNumber(remainderAndAddition));
        }
        valueUndescoreLine = returnCategoryOfNumber(remainderAndAddition);
        if(i == 0 && markerPrintHead) {
            printHead(divisor);
        } else {
            System.out.println(generateGaps(gapsBefore)+remainderAndAddition);
        }
        int idealIntermediateDivisor = printSuperDividend(remainderAndAddition);
        setResult(idealIntermediateDivisor/divisor);
        generateUnderscore(gapsBefore, valueUndescoreLine);
        firstPart = returnRemainder(remainderAndAddition, idealIntermediateDivisor);
            if(firstPart == 0 && remainderAndAddition != 0) {
                for(int j = 0;j < extraZeroInResult;j++) { 
                    setResult(0);
                }
                makeColumn(0);
                break;
            } else if (remainderAndAddition == 0) {
                System.out.println(generateGaps(gapsBefore)+"0");
                break;
            }else {
                increaseGapsBefore(valueUndescoreLine - returnCategoryOfNumber(firstPart));
            }
            if(i == 19) {
                System.out.println(generateGaps(gapsBefore)+"...");
            }
        }
    }
    /**
     * 
     * @param remainderAndAddition
     * @return 
     */
    public int printSuperDividend(int remainderAndAddition) {
        int idealIntermediateDivisor = generateIdealDivided(remainderAndAddition, divisor);
        int differenceDigitsInSteps = returnCategoryOfNumber(remainderAndAddition) - returnCategoryOfNumber(idealIntermediateDivisor);
        System.out.println(generateGaps(gapsBefore + differenceDigitsInSteps)+idealIntermediateDivisor);  
        return idealIntermediateDivisor;
    }
    /**
     * 
     * @param divisor 
     */
    public void printHead(int divisor) {
        showDividend();
        System.out.println(" | "+divisor);
        markerPrintHead = false;
    }
    
    static int markerNextNumber = 1;
    static int extraZeroInResult = 0;

    /**
     * Check how many digits from dividend we will use every step
     * @param firstDigit
     * @return 
     */
    public int generateSuitablePartOfDividend(int firstDigit) {
        int suitablePartDividend = firstDigit;
            int j = 0;
            do {
                try{
                    extraZeroInResult++;
                    suitablePartDividend = generateNumberFromTwo(suitablePartDividend, dividend[++markerNextNumber]);
                    
                }catch(ArrayIndexOutOfBoundsException e) {
                    if(suitablePartDividend == 0) {
                        break;
                    }
                    if(j > 0) {
                        setResult(0);
                    }
                    addCommaInResult();
                        j++;
                        suitablePartDividend = generateNumberFromTwo(suitablePartDividend, 0);
                }
            }while(suitablePartDividend < divisor);
        return suitablePartDividend;
    }
    
    static int markerCountWholePart = 1;
    
    /**
     * Method which once put comma in result
     */
    public void addCommaInResult() {
        if(markerCountWholePart == 1) {
            setResult(",");
            markerCountWholePart++;
        }
    }
    /**
     * Generate ideal dividend which contain whole number divisors and no more then parameter dividend
     * @param dividend
     * @return 
     */
    public int generateIdealDivided(int dividend, int divisor) {
            int intermediateSuperDividend = 0;
            do {
                intermediateSuperDividend = intermediateSuperDividend + divisor;
            }while(intermediateSuperDividend <= dividend && dividend != 0);
            intermediateSuperDividend = intermediateSuperDividend - divisor;
            return intermediateSuperDividend;
    }
    /**
     * 
     */
    public void showDividend() {
        for (int i = 1; i < dividend.length; i++) {
            System.out.print(dividend[i]);
        }
    }
    /**
     * 
     * @param dividend
     * @param idealDividend
     * @return 
     */
    public static int returnRemainder(int dividend, int idealDividend) {
            int remainder;
            remainder = dividend - idealDividend;
            return remainder;
    }
    /**
     * 
     * @param gapsBeforeUnderscore
     * @param value 
     */
    public void generateUnderscore(int gapsBeforeUnderscore, int value) {
        System.out.println(generateGaps(gapsBeforeUnderscore)+generateLine(value));
    }
    /**
     * 
     * @param valueOfGaps
     * @return 
     */
    public static String generateGaps(int valueOfGaps) {
        String longGaps = "";
        for( int i = 0; i < valueOfGaps ;i++) {
            longGaps = longGaps + " ";
        }
        return longGaps;
    }
    /**
     * 
     * @param valueOfLine
     * @return 
     */
    public static String generateLine(int valueOfLine) {
        String longLine = "";
        for( int i = 0; i < valueOfLine ;i++) {
            longLine = longLine + "-";
        }
        return longLine;
    }
    /**
     * 
     * @param number
     * @return 
     */    
    public static int returnCategoryOfNumber(int number) {
        int localCounter = 1;
        int elser = 10;
        while(number >= elser) {
            elser = elser * 10;
            localCounter++;
        }
        return localCounter;
    }
}
